# -*- mode: Perl -*-
# /=====================================================================\ #
# |  longtable                                                          | #
# | Implementation for LaTeXML                                          | #
# |=====================================================================| #
# | Part of LaTeXML:                                                    | #
# |  Public domain software, produced as part of work done by the       | #
# |  United States Government & not subject to copyright in the US.     | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Package::Pool;
use strict;
use warnings;
use LaTeXML::Package;

#======================================================================
# NOTE: The way the headers & footers are captured causes trailing \hlines
# to generate empty rows.
#======================================================================
# Environment \begin{longtable}[align]{pattern} ... \end{longtable}
DefMacro('\longtable[]{}',
  '\@longtable@bindings{#2}\@@longtable[#1]{#2}\@start@alignment');
DefMacro('\endlongtable',
  '\@finish@alignment\@end@tabular');
# {longtable*} is defined in revtex4-1 to be able to span a two column document
DefMacro('\csname longtable*\endcsname []{}',
  '\@longtable@bindings{#2}\@@longtable[#1]{#2}\@start@alignment');
DefMacro('\csname endlongtable*\endcsname',
  '\@finish@alignment\@end@tabular');

DefMacro('\@gobble@optional[]', Tokens());

DefConstructor('\@@longtable [] Undigested DigestedBody',
  "<ltx:table xml:id='#id' inlist='lot' labels='#label'>"
    . "#tags"
    . "?#caption(<ltx:caption>#caption</ltx:caption>)"
    . "?#toccaption(<ltx:toccaption>#toccaption</ltx:toccaption>)"
    . "#3"
    . "</ltx:table>",
  reversion    => '\begin{longtable}[#1]{#2}#3\end{longtable}',
  beforeDigest => sub { $_[0]->bgroup; Let('\pagebreak', '\@gobble@optional'); },
  afterDigest  => sub {
    my ($stomach, $whatsit) = @_;
    $whatsit->setProperties(%{ LookupValue('LONGTABLE_PROPERTIES') || {} });
    # Insert caption and toccaption, if any were encountered.
    if (my $caption = LookupValue('LONGTABLE_CAPTION')) {
      $whatsit->setProperty(caption => $caption); }
    if (my $label = LookupValue('LONGTABLE_LABEL')) {
      $whatsit->setProperty(label => $label); }
    if (my $toccaption = LookupValue('LONGTABLE_TOCCAPTION')) {
      $whatsit->setProperty(toccaption => $toccaption); }
    my $alignment = LookupValue('Alignment');
    # Reinsert the head and foot into the alignment.
    if (my $head = LookupValue('LONGTABLE_HEAD')) {
      $alignment->prependRows(@{$head}); }
    if (my $foot = LookupValue('LONGTABLE_FOOT')) {
      $alignment->appendRows(@{$foot}); }
    return; },
  mode => 'text');

DefPrimitive('\@longtable@bindings AlignmentTemplate', sub { longtableBindings($_[1]); });

sub longtableBindings {
  my ($template) = @_;
  tabularBindings($template, guess_headers => 0);
  Let('\endfirsthead', '\@longtable@endfirsthead');
  Let('\endhead',      '\@longtable@endhead');
  Let('\endfoot',      '\@longtable@endfoot');
  Let('\endlastfoot',  '\@longtable@endlastfoot');
  Let('\caption',      '\@longtable@caption');
  Let('\label',        '\@longtable@label');
  AssignValue(LONGTABLE_LABEL      => undef, 'global');    # Clear these vars.
  AssignValue(LONGTABLE_CAPTION    => undef, 'global');
  AssignValue(LONGTABLE_TOCCAPTION => undef, 'global');
  AssignValue(LONGTABLE_HEAD       => undef, 'global');
  AssignValue(LONGTABLE_FOOT       => undef, 'global');
  ## properties happen too late!!!
  AssignValue(LONGTABLE_PROPERTIES => { RefStepCounter('table') }, 'global');

  return; }

#======================================================================
# These macros appear within the longtable, at the beginning.
# They cut of the previous lines to be used as headers or footers.

DefMacro('\@longtable@endfirsthead', '\crcr\noalign{\@longtable@grab{FIRSTHEAD}}');
DefMacro('\@longtable@endhead',      '\crcr\noalign{\@longtable@grab{HEAD}}');
DefMacro('\@longtable@endfoot',      '\crcr\noalign{\@longtable@grab{FOOT}}');
DefMacro('\@longtable@endlastfoot',  '\crcr\noalign{\@longtable@grab{LASTFOOT}}');
DefMacro('\@longtable@kill',         '\crcr\noalign{\@longtable@kill@marker}');

DefPrimitive('\@longtable@grab{}', sub {
    my ($stomach, $name) = @_;
    $name = ToString($name);
    my $alignment = LookupValue('Alignment');
    # Remove all preceding rows.
    my @rows = ();
    while (my $row = $alignment->removeRow) {
      map { $$_{thead}{column} = 1; } $row->columns;
      unshift(@rows, $row); }
    if (($name eq 'FIRSTHEAD') || (($name eq 'HEAD') && !LookupValue('LONGTABLE_HEAD'))) {
      AssignValue(LONGTABLE_HEAD => [@rows], 'global'); }
    elsif (($name eq 'LASTFOOT') || (($name eq 'FOOT') && !LookupValue('LONGTABLE_FOOT'))) {
      AssignValue(LONGTABLE_FOOT => [@rows], 'global'); }
    return; });

DefConstructor('\@longtable@kill@marker', '', reversion => '\kill',
  afterDigest => sub { LookupValue('Alignment')->removeRow; return; });

#======================================================================
# Caption gets redefined.  We'll need to grab it and make it part
# of the table, rather than the tabular.
DefMacro('\@longtable@caption[]{}',
  '\@longtable@@toccaption{\lx@format@toctitle@@{table}{\ifx.#1.#2\else#1\fi}}'
    . '\@longtable@@caption{\lx@format@title@@{table}{#2}}');

DefPrimitive('\@longtable@label Semiverbatim', sub {
    AssignValue(LONGTABLE_LABEL => CleanLabel(ToString($_[1])), 'global');
    return; });
DefPrimitive('\@longtable@@caption{}', sub {
    AssignValue(LONGTABLE_CAPTION => DigestText($_[1]), 'global');
    return; });
DefPrimitive('\@longtable@@toccaption{}', sub {
    AssignValue(LONGTABLE_TOCCAPTION => DigestText($_[1]), 'global');
    return; });

#======================================================================
# Not used, but must be defined.
DefRegister('\LTleft'      => Glue('0pt plus 1fill'));
DefRegister('\LTright'     => Glue('0pt plus 1fill'));
DefRegister('\LTpre'       => Glue('12pt plus 4pt minus 4pt'));
DefRegister('\LTpost'      => Glue('12pt plus 4pt minus 4pt'));
DefRegister('\LTcapwidth'  => Dimension('4in'));
DefRegister('\LTchunksize' => Number(200));
DefRegister('\LT@cols'     => Number(0));
DefRegister('\LT@rows'     => Number(0));
Let('\c@LTchunksize', '\LTchunksize');
RawTeX(<<'EOL');
\newbox\LT@head
\newbox\LT@firsthead
\newbox\LT@foot
\newbox\LT@lastfoot
\newbox\LT@gbox
EOL
Let('\setlongtables', '\relax');
#======================================================================
1;
